/*
 * rayqueue.c
 *
 *  Created on: Feb 22, 2010
 *      Author: pitidecaner
 *
 *      define queue to store rays in ther way get solved.
 *      it does not realy matter if we implemet it FIFO or LIFO
 *         his time LIFO
 *
 *      has functions to store them, and to recover them
 *
 */
#include <stdlib.h>
#include "types.h"
#include "rayqueue.h"
#include "measures/measuring.h"


/**
 * initialize ray queue
 * input
 *       copies: number of threads to make their own memory space
 * output: 0 if ok
 *         != if any error happens, see system error
 */
inline rayqueue * rt_rq_initialize (int copies){
	rayqueue * q;
	ray * r;
	int i,cola;

	if ((q= malloc(sizeof(rayqueue)*copies))== NULL)
		return NULL;

	for (cola =0; cola < copies; cola++){
		q[cola].cola = NULL;
		q[cola].rayos = NULL;

		/* alocate 3 rays, we dont need more,
		 * one being procesed,
		 * and 2 for reflection and reflaction
		 */
		for (i=0; i<64; i++){
			r =  malloc(sizeof(ray));
			r->next = q[cola].rayos;
			q[cola].rayos = r;
		}

		q[cola].numrays = 0;
	}
	return q;
}

/**
 * delete ray queue, frees resources alocated
 * input q: rayqueue opaque pointer
 */
inline void rt_rq_delete (rayqueue *q, int threads){
	ray *r;
	int i;

	for (i =0; i< threads; i++){
		r = q[i].rayos;
		while (r){
			q[i].rayos = r->next;
			free (r);
			r = q[i].rayos;
		}
	}
	free (q);
}

/**
 * pops a ray from the queue, if not returns NULL
 * input q: rayqueue opaque pointer
 * output: Ray in queue if exists
 *         NULL if empty
 */
inline ray *rt_rq_get_ray (rayqueue *q, int c){

	ray * r = (ray *)q[c].cola;
	if (r){
		q[c].cola = r->next;
		q[c].numrays --;
	}
	return r;
}

/**
 * push a ray in the queue
 * input q: rayqueue opaque pointer
 *       r: ray to be enqueued
 *       c: queue to use, multiple threads
 * output: 0 if ok
 *         != if error
 */
inline void rt_rq_add_ray(rayqueue *q, ray *r, int c){

	r->next = q[c].cola;
	q[c].cola = r;
	q[c].numrays ++;
}

/**
 * get size of que queue
 */
inline long rt_rq_get_size(rayqueue *q, int c){
	return q[c].numrays;
}


/**
 * create ray or use an unused ray
 */
inline ray * rt_rq_newray(rayqueue *q, int c){
	ray *r;
	r = (ray *)q[c].rayos;
	q[c].rayos = r->next;
	r->next = NULL;
	return r;
}
/**
 * store ray mem area for further use
 */
inline void  rt_rq_eraseray(rayqueue *q,ray *r, int c){
	r->next = q[c].rayos;
	q[c].rayos = r;
}


